/**
 * @file LogFormatter.h
 * @author  haifeng (haifengxiao@icloud.com)
 * @brief
 * @version 0.1
 * @date 2021-07-06
 *
 * @copyright Copyright (c) 2021
 *
 */

#pragma once

#include <map>
#include <memory>
#include <vector>
#include <string>
#include <functional>

#include "LogLevel.h"
#include "LogEvent.h"

namespace Chen {
    namespace Log {

        class Logger;

        class LogFormatter {
        public:
            typedef std::shared_ptr<LogFormatter> ptr;

            /**
             * @brief Construct a new Log Formatter object
             *
             * @param pattern log pattern
             *  %m Message
             *  %p Log level
             *  %r Tatal minisecond
             *  %c Log name
             *  %t Thread id
             *  %n Enter
             *  %d Time
             *  %f Filenamec
             *  %l Line
             *  %T Table
             *  %F Fiber id
             *  %N Thread name
             *
             *  default pattern "%d{%Y-%m-%d %H:%M:%S}%T%t%T%N%T%F%T[%p]%T[%c]%T%f:%l%T%m%n"
             */
            LogFormatter(const std::string& pattern);

        public:

            /**
             * @brief specific log item
             *
             */
            class FormatItem {
            public:
                typedef std::shared_ptr<FormatItem> ptr;
                virtual ~FormatItem() {}

                /**
                 * @brief format
                 *
                 */
                virtual void format(std::ostream& os, std::shared_ptr<Logger> logger
                    , LogLevel::Level level, LogEvent::ptr event) = 0;
            };

            /**
             * @brief
             *
             * @param logger
             * @param level
             * @param event
             * @return std::string
             */
            std::string format(std::shared_ptr<Logger> logger
                , LogLevel::Level level, LogEvent::ptr event);

            /**
             * @brief
             *
             * @param ofs
             * @param logger
             * @param level
             * @param event
             * @return std::ostream&
             */
            std::ostream& format(std::ostream& ofs, std::shared_ptr<Logger> logger
                , LogLevel::Level level, LogEvent::ptr event);

            /**
             * @brief parse the pattern
             *
             */
            void init();

            /**
             * @brief whether there is an error in the prasing process
             *
             * @return true
             * @return false
             */
            bool isError() const { return m_error; }

            /**
             * @brief Get the Pattern object
             *
             * @return const std::string
             */
            const std::string getPattern() const { return m_pattern; }

        private:
            std::string m_pattern;
            bool m_error;
            std::vector<FormatItem::ptr> m_items;
        };

    }//namespace Log
}//namespace Chen